using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
using System.ComponentModel;

namespace PotonCapture
{
    public class MouseHook : HookBase
    {
        protected enum MouseMessages
        {
            MOUSEMOVE = 0x0200,
            LBUTTONDOWN = 0x0201,
            LBUTTONUP = 0x0202,
            LBUTTONDBLCLK = 0x0203,
            RBUTTONDOWN = 0x0204,
            RBUTTONUP = 0x0205,
            RBUTTONDBLCLK = 0x0206,
            MBUTTONDOWN = 0x0207,
            MBUTTONUP = 0x0208,
            MBUTTONDBLCLK = 0x0209,
            MOUSEWHEEL = 0x020A,
        }

        public class MouseHookEventArgs : MouseEventArgs
        {
            protected bool _cancel;

            public bool Cancel
            {
                get { return _cancel; }
                set { _cancel = value; }
            }

            public MouseHookEventArgs(MouseButtons button, int clicks, int x, int y, int delta)
                : base(button, clicks, x, y, delta)
            {
            }
        }
        public delegate void MouseHookEventHandler(object sender, MouseHookEventArgs e);

        public MouseHookEventHandler Event
        {
            get { return _hookEvent; }
            set { _hookEvent = value; }
        }

        protected MouseHookEventHandler _hookEvent;

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        protected struct KeyboardHookStruct
        {
            public Point pt;
            public int mouseData;
            public int flags;
            public int time;
            public int dwExtraInfo;
        }

        public MouseHook() : base(HookTypes.MouseLowLevel, true)
        {
            if (Environment.OSVersion.Platform != PlatformID.Win32NT)
            {
                throw new PlatformNotSupportedException();
            }
        }

        protected override int OnHook(int nCode, IntPtr wParam, IntPtr lParam)
        {
//            System.Diagnostics.Debug.WriteLine("mouse hook");
            if (nCode >= 0 && _hookEvent != null)
            {
                KeyboardHookStruct hookStruct = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
                MouseHookEventArgs e = null;
                switch (wParam.ToInt32())
                {
                    case (int)MouseMessages.LBUTTONDOWN:
                        e = new MouseHookEventArgs(MouseButtons.Left, 0, hookStruct.pt.X, hookStruct.pt.Y, 0);
                        break;
                    case (int)MouseMessages.MBUTTONDOWN:
                        e = new MouseHookEventArgs(MouseButtons.Middle, 0, hookStruct.pt.X, hookStruct.pt.Y, 0);
                        break;
                    case (int)MouseMessages.RBUTTONDOWN:
                        e = new MouseHookEventArgs(MouseButtons.Right, 0, hookStruct.pt.X, hookStruct.pt.Y, 0);
                        break;
                }
                if (e != null)
                {
                    _hookEvent(this, e);
                    if (e.Cancel)
                    {
                        return -1;
                    }
                }
            }
            return base.OnHook(nCode, wParam, lParam);
        }
    }
}
